<template>
  <el-dialog v-model="dialogVisible" :title="parameter.title" width="780px" lock-scroll destroy-on-close draggable>
    <el-form ref="formRef" :model="parameter.role">
      <el-form-item prop="routes">
        <el-tree
          ref="treeRef"
          :icon="ElMenuIcon"
          :data="resourceData"
          :props="{ children: 'children', label: 'description', class: treeNodeClass }"
          :default-checked-keys="parameter.role.routes"
          node-key="route"
          class="menu-data-tree"
          show-checkbox
          highlight-current
          default-expand-all
        />
      </el-form-item>
    </el-form>
    <template #footer>
      <el-button @click="dialogVisible = false">取消</el-button>
      <el-button type="primary" @click="handleSubmit">提交</el-button>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
import type { FormInstance, TreeInstance } from "element-plus";
import type { ResultData, SysRole, SysResource } from "@/api/interface";
import { ref, watch } from "vue";
import { getResourceListApi } from "@/api/modules/system/resource";
import { ElMessage } from "element-plus";

import ElMenuIcon from "~icons/ep/menu";

defineOptions({
  name: "SystemRoleDistributionResource"
});

/** 系统角色 */
interface EditProps {
  /** 标题 */
  title: string;
  /** 待编辑的角色 */
  role: Partial<SysRole.ResourceForm>;
  /** 提交表单的Api */
  submitApi?: (params: any) => Promise<ResultData<boolean>>;
}

/** 表单实例 */
const formRef = ref<FormInstance>();
/** 树实例 */
const treeRef = ref<TreeInstance>();
/** dialog 状态 */
const dialogVisible = ref(false);
/** 资源列表 */
const resourceData = ref<SysResource.GroupResult[]>([]);
/** 父组件传过来的参数 */
const parameter = ref<EditProps>({
  title: "",
  role: {
    routes: []
  }
});

/**
 * 接收父组件参数
 *
 * @param params 父组件传过来的参数
 * @returns void
 */
const acceptParams = (params: EditProps) => {
  parameter.value = params;
  dialogVisible.value = true;
};

/**
 * 初始化表单
 *
 * 1. 重置表单
 * 2. 获取菜单树
 * 3. 加载表单数据
 *
 * @returns void
 */
const initFormInline = () => {
  formRef.value?.resetFields();
  treeRef.value?.setCheckedKeys([]);

  getResourceListApi().then(({ data }) => {
    resourceData.value = data;
  });
};

/**
 * 树节点样式
 *
 * @param node 树节点
 * @returns 节点样式
 */
const treeNodeClass = (node: any) => {
  let addClass = true; // 添加叶子节点同行显示样式
  for (const key in node.children) {
    // 如果存在子节点非叶子节点，不添加样式
    if (node.children[key].children?.length ?? 0 > 0) {
      addClass = false;
      break;
    }
  }
  return addClass ? "penultimate-node" : "";
};

/**
 * 提交表单
 *
 * 1. 校验表单
 * 2. 表单数据处理
 * 3. 提交表单
 * 4. 提交结果处理
 * 5. 异常处理
 *
 * @returns void
 */
const handleSubmit = () => {
  formRef.value
    // 1. 校验表单
    ?.validate()
    // 2. 表单数据处理
    .then(() => {
      parameter.value.role.routes = treeRef.value?.getCheckedKeys() as string[];
      // 过滤数组中的undefined
      return parameter.value.role.routes.filter(Boolean);
    })
    // 3. 提交表单
    .then(role => {
      return parameter.value.submitApi!({ id: parameter.value.role.id!, routes: role });
    })
    // 4. 提交结果处理
    .then(({ data }) => {
      if (data) {
        ElMessage.success({ message: `${parameter.value.title}成功！` });
        dialogVisible.value = false;
      } else {
        ElMessage.error({ message: `${parameter.value.title}失败！` });
      }
    })
    // 5. 异常处理
    .catch((error: Error) => {
      if (error.message) ElMessage.error({ message: `${parameter.value.title}异常：${error.message}` });
      else ElMessage.error({ message: "请检查表单数据是否填写完整！" });
    });
};

// 监听 dialogVisible 的变化
watch(dialogVisible, val => {
  if (val) {
    initFormInline();
  }
});

// 暴露给父组件的属性和方法
defineExpose({
  acceptParams
});
</script>

<style lang="scss" scoped>
.menu-data-tree {
  width: 100%;
  padding: 5px;
}
:deep(.penultimate-node) {
  .el-tree-node__children {
    padding-left: 40px;
    line-height: 100%;
    white-space: pre-wrap;
    .el-tree-node {
      display: inline-block;
    }
    .el-tree-node__content {
      width: 160px;
      padding-right: 5px;
      padding-left: 5px !important;
      .el-tree-node__expand-icon.is-leaf {
        display: none;
      }
      .el-tree-node__label {
        overflow: hidden;
        text-overflow: ellipsis;
      }
    }
  }
}
</style>
